package logic_basics

import (
	"APT/internal/dao"
	"APT/internal/library/hgorm/handler"
	"APT/internal/library/hgorm/hook"
	"APT/internal/model"
	"APT/internal/model/entity"
	"APT/internal/model/input/input_basics"
	"APT/internal/model/input/input_car"
	"APT/internal/model/input/input_food"
	"APT/internal/model/input/input_form"
	"APT/internal/model/input/input_spa"
	"APT/internal/service"
	"context"
	"database/sql"
	"errors"
	openApi "github.com/Qzm6826/yly-go-sdk"
	"github.com/gogf/gf/v2/container/gvar"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"strings"
)

type sBasicsPrinter struct{}

func NewBasicsPrinter() *sBasicsPrinter {
	return &sBasicsPrinter{}
}

func init() {
	service.RegisterBasicsPrinter(NewBasicsPrinter())
}

// Model 打印机ORM模型
func (s *sBasicsPrinter) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
	return handler.Model(dao.SysPrinter.Ctx(ctx), option...)
}

// List 获取打印机列表
func (s *sBasicsPrinter) List(ctx context.Context, in *input_basics.PrinterListInp) (list []*input_basics.PrinterListModel, totalCount int, err error) {
	mod := s.Model(ctx).WithAll()

	// 字段过滤
	mod = mod.Fields(input_basics.PrinterListModel{})

	// 打印机名称
	if !g.IsEmpty(in.PrinterName) {
		mod = mod.WhereLike(dao.SysPrinter.Columns().PrinterName, "%"+in.PrinterName+"%")
	}

	// 第三方应用ID
	if !g.IsEmpty(in.ClientId) {
		mod = mod.WhereLike(dao.SysPrinter.Columns().ClientId, "%"+in.ClientId+"%")
	}

	// 第三方应用秘钥
	if !g.IsEmpty(in.ClientSecret) {
		mod = mod.WhereLike(dao.SysPrinter.Columns().ClientSecret, "%"+in.ClientSecret+"%")
	}

	// 机器码
	if !g.IsEmpty(in.MachineCode) {
		mod = mod.WhereLike(dao.SysPrinter.Columns().MachineCode, "%"+in.MachineCode+"%")
	}

	// 分页
	if in.Pagination {
		mod = mod.Page(in.Page, in.PerPage)
	}

	// 排序
	mod = mod.OrderDesc(dao.SysPrinter.Columns().Sort).OrderDesc(dao.SysPrinter.Columns().Id)
	//mod = mod.Hook(hook2.PmsFindLanguageValueHook)

	// 查询数据
	if in.Pagination {
		if err = mod.ScanAndCount(&list, &totalCount, false); err != nil && !errors.Is(err, sql.ErrNoRows) {
			err = gerror.Wrap(err, "获取打印机列表失败，请稍后重试！")
			return
		}
	} else {
		if err = mod.Scan(&list); err != nil && !errors.Is(err, sql.ErrNoRows) {
			err = gerror.Wrap(err, "获取打印机列表失败，请稍后重试！")
			return
		}
	}
	return
}

// Edit 修改/新增打印机
func (s *sBasicsPrinter) Edit(ctx context.Context, in *input_basics.PrinterEditInp) (err error) {
	return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {

		// 修改
		if in.Id > 0 {
			if _, err = s.Model(ctx).
				Fields(input_basics.PrinterUpdateFields{}).
				WherePri(in.Id).Data(in).Update(); err != nil {
				err = gerror.Wrap(err, "修改打印机失败，请稍后重试！")
			}
			return
		}

		// 新增
		if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).
			Fields(input_basics.PrinterInsertFields{}).
			Data(in).OmitEmptyData().Insert(); err != nil {
			err = gerror.Wrap(err, "新增打印机失败，请稍后重试！")
		}

		return
	})
}

// Delete 删除打印机
func (s *sBasicsPrinter) Delete(ctx context.Context, in *input_basics.PrinterDeleteInp) (err error) {

	if _, err = s.Model(ctx).WherePri(in.Id).Delete(); err != nil {
		err = gerror.Wrap(err, "删除打印机失败，请稍后重试！")
		return
	}
	return
}

// MaxSort 获取打印机最大排序
func (s *sBasicsPrinter) MaxSort(ctx context.Context, in *input_basics.PrinterMaxSortInp) (res *input_basics.PrinterMaxSortModel, err error) {
	if err = dao.SysPrinter.Ctx(ctx).Fields(dao.SysPrinter.Columns().Sort).OrderDesc(dao.SysPrinter.Columns().Sort).Scan(&res); err != nil {
		err = gerror.Wrap(err, "获取打印机最大排序，请稍后重试！")
		return
	}

	if res == nil {
		res = new(input_basics.PrinterMaxSortModel)
	}

	res.Sort = input_form.DefaultMaxSort(res.Sort)
	return
}

// View 获取打印机指定信息
func (s *sBasicsPrinter) View(ctx context.Context, in *input_basics.PrinterViewInp) (res *input_basics.PrinterViewModel, err error) {
	if err = s.Model(ctx).WithAll().WherePri(in.Id).Scan(&res); err != nil {
		err = gerror.Wrap(err, "获取打印机信息，请稍后重试！")
		return
	}

	return
}

// Status 更新司机状态
func (s *sBasicsPrinter) Status(ctx context.Context, in *input_basics.PrinterStatusInp) (err error) {
	return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {

		if _, err = s.Model(ctx).WherePri(in.Id).Data(g.Map{
			dao.SysPrinter.Columns().Status: in.Status,
		}).Update(); err != nil {
			err = gerror.Wrap(err, "更新打印机状态失败，请稍后重试！")
			return
		}

		return
	})
}

// PrinterCarOrder 打印接送机订单
func (s *sBasicsPrinter) PrinterCarOrder(ctx context.Context, in *input_basics.PrinterCarOrderInp) (err error) {

	// 获取打印配置
	var PrinterConfig *model.PrinterSettingConfig
	if PrinterConfig, err = service.BasicsConfig().GetCarPrinterSettingConfig(ctx); err != nil {
		return
	}

	// 判断是否开启打印功能
	if PrinterConfig.IsOpen == 2 {
		err = gerror.New("未开启打印功能，请稍后重试！")
		return
	}

	if g.IsEmpty(PrinterConfig.PrinterIds) {
		err = gerror.New("未配置打印机，请稍后重试！")
		return
	}

	// 获取打印机信息，默认一号打印机 todo	mod = mod.
	var printerArr []*entity.SysPrinter
	if err = dao.SysPrinter.Ctx(ctx).
		WhereIn(dao.SysPrinter.Columns().Id, strings.Split(PrinterConfig.PrinterIds, ",")).
		WithAll().
		Scan(&printerArr); err != nil {
		err = gerror.Wrap(err, "获取打印机信息失败，请稍后重试！")
		return
	}

	// 获取订单信息
	var carOrder *input_car.CarOrderViewModel
	if !g.IsEmpty(in.OrderId) {
		if err = dao.CarOrder.Ctx(ctx).WherePri(in.OrderId).WithAll().Scan(&carOrder); err != nil {
			err = gerror.Wrap(err, "获取订单信息失败，请稍后重试！")
			return
		}
	} else {
		if err = dao.CarOrder.Ctx(ctx).Where(dao.CarOrder.Columns().OrderSn, in.OrderSn).WithAll().Scan(&carOrder); err != nil {
			err = gerror.Wrap(err, "获取订单信息失败，请稍后重试！")
			return
		}
	}

	// 打印内容
	var orderType = "住一自营"
	var pickUpSign = "否"
	if carOrder.OrderType == "INNN" {
		orderType = "INNN"
	}
	if carOrder.ServiceType == "PICKUP" && carOrder.PickUpSign == "Y" {
		pickUpSign = "是"
	}

	// 循环打印机, 判断打印机状态，状态为1时打印
	for _, printer := range printerArr {
		if printer.Status != 1 {
			continue
		}

		var content = ""
		content = content +
			"<MN>" + gvar.New(printer.PrintTimes).String() + "</MN>" +
			"<FS><center>" + orderType + "</center></FS>" + "\\r\\n" +
			//"<FH>" +
			"订单编号：" + carOrder.OrderSn + "\\r\\n" + "\\r" +
			"出发地：" + carOrder.StartServiceAddress.Name + "\\r\\n" +
			"到达地：" + carOrder.EndServiceAddress.Name + "\\r\\n" +
			"用车时间：" + gvar.New(carOrder.BookStartTime).String() + "\\r\\n" +
			"\\r\\n" +
			"订单金额：" + gvar.New(carOrder.OrderAmount).String() + "JPY\\r\\n" +
			"支付时间：" + gvar.New(carOrder.PayTime).String() + "\\r\\n" +
			"\\r\\n" +
			"预订人信息：\\r\\n" +
			"预订人：" + carOrder.BookingName + "\\r\\n" +
			"电话：" + carOrder.PhoneArea + carOrder.BookingMobile + "\\r\\n" +
			"\\r\\n" +
			"人数：\\r\\n" +
			"成人：" + gvar.New(carOrder.AdultNum).String() + "\\r\\n" +
			"儿童：" + gvar.New(carOrder.ChildNum).String() + "\\r\\n" +
			"\\r\\n" +
			"附加服务：\\r\\n" +
			"举牌服务：" + pickUpSign + "\\r\\n" +
			"婴儿座椅：" + gvar.New(carOrder.ChildSeatAddNum).String() + "\\r\\n" +
			"\\r\\n" +
			"紧急联系人：\\r\\n" +
			"联系人：" + carOrder.EmergencyName + "\\r\\n" +
			"电话：" + carOrder.EmergencyPhoneArea + carOrder.EmergencyMobile + "\\r\\n" +
			"备注：" + carOrder.MemberMessage + "\\r\\n" +
			//"</FH>" +
			"\\r\\n"
		if carOrder.DispatchStatus != "WAIT" && carOrder.PayStatus == "HAVE_PAID" {
			content = content +
				"<FS>司机：" + "\\r\\n" +
				"司机姓名：" + carOrder.DriverDetail.Name + "\\r\\n" +
				"司机手机：" + carOrder.DriverDetail.PhoneArea + carOrder.DriverDetail.Phone + "</FS>\\r\\n"
		}
		content = content + "\\r\\n" + "\\r\\n"

		// 开始打印
		// 新建一个配置实例
		conf := openApi.NewConfig(printer.ClientId, printer.ClientSecret)

		// 获取 token 并设置
		oauth := openApi.NewAuthClient(conf)
		tokenData := oauth.GetAccessToken()
		conf.SetToken(tokenData)

		// 新建一个 API 实例
		client := openApi.NewClient(conf)

		// 添加一个打印机。未绑定打印机，需先调用此方法
		//_, _ = client.SetPrinter.AddPrinter(printer.MachineCode, printer.MachineKey, printer.PrinterName)

		// 调用服务 API
		_, _ = client.PrintService.TextPrint(printer.MachineCode, content, carOrder.OrderSn, 0)
	}

	return
}

// PrinterSpaOrder 打印按摩订单
func (s *sBasicsPrinter) PrinterSpaOrder(ctx context.Context, in *input_basics.PrinterCarOrderInp) (err error) {

	// 获取打印配置
	var PrinterConfig *model.PrinterSettingConfig
	if PrinterConfig, err = service.BasicsConfig().GetSpaPrinterSettingConfig(ctx); err != nil {
		return
	}

	// 判断是否开启打印功能
	if PrinterConfig.IsOpen == 2 {
		err = gerror.New("未开启打印功能，请稍后重试！")
		return
	}

	if g.IsEmpty(PrinterConfig.PrinterIds) {
		err = gerror.New("未配置打印机，请稍后重试！")
		return
	}

	// 获取打印机信息，默认一号打印机 todo	mod = mod.
	var printerArr []*entity.SysPrinter
	if err = dao.SysPrinter.Ctx(ctx).
		WhereIn(dao.SysPrinter.Columns().Id, strings.Split(PrinterConfig.PrinterIds, ",")).
		WithAll().
		Scan(&printerArr); err != nil {
		err = gerror.Wrap(err, "获取打印机信息失败，请稍后重试！")
		return
	}

	// 获取订单信息
	var spaOrder *input_spa.SpaOrderViewModel
	if !g.IsEmpty(in.OrderId) {
		if err = dao.SpaOrder.Ctx(ctx).WherePri(in.OrderId).WithAll().Hook(hook.PmsFindLanguageValueHook).Scan(&spaOrder); err != nil {
			err = gerror.Wrap(err, "获取订单信息失败，请稍后重试！")
			return
		}
	} else {
		if err = dao.SpaOrder.Ctx(ctx).Where(dao.SpaOrder.Columns().OrderSn, in.OrderSn).WithAll().Hook(hook.PmsFindLanguageValueHook).Scan(&spaOrder); err != nil {
			err = gerror.Wrap(err, "获取订单信息失败，请稍后重试！")
			return
		}
	}

	// 打印内容
	var orderType = "按摩"
	var serviceType = "到店"
	if spaOrder.ServiceType != 1 {
		serviceType = "上门"
	}

	// 循环打印机, 判断打印机状态，状态为1时打印
	for _, printer := range printerArr {
		if printer.Status != 1 {
			continue
		}

		var content = ""
		content = content +
			"<MN>" + gvar.New(printer.PrintTimes).String() + "</MN>" +
			"<FS><center>" + orderType + "</center></FS>" + "\\r\\n" +
			//"<FH>" +
			"订单编号：" + spaOrder.OrderSn + "\\r\\n" +
			"订单金额：" + gvar.New(spaOrder.OrderAmount).String() + "JPY\\r\\n" +
			"支付时间：" + gvar.New(spaOrder.PayTime).String() + "\\r\\n" +
			"\\r" +
			"服务方式：" + serviceType + "\\r\\n"
		if spaOrder.ServiceType == 2 {
			content = content +
				"服务地址：" + spaOrder.PropertyDetail.Name + "\\r\\n" +
				"房间号：" + spaOrder.RoomNo + "\\r\\n"
		}
		content = content +
			"预约时间：" + gvar.New(spaOrder.BookStartTime).String() + "\\r\\n" +
			"\\r\\n" +
			"预约项目：\\r\\n" +
			"\\t" + spaOrder.ServiceDetail.Name + "\\r\\n" +
			"\\t" + spaOrder.GoodsDetail.GoodsName + " *" + gvar.New(spaOrder.GoodsNum).String() + "次\\r\\n" +
			"\\r\\n" +
			"预订人信息：\\r\\n" +
			"预订人：" + spaOrder.BookingName + "\\r\\n" +
			"电话：" + spaOrder.PhoneArea + spaOrder.BookingMobile + "\\r\\n" +
			"\\r\\n" +
			"备注：" + spaOrder.MemberMessage + "\\r\\n" +
			//"</FH>" +
			"\\r\\n"
		if spaOrder.DispatchStatus == "DONE" && spaOrder.PayStatus == "HAVE_PAID" {
			content = content + "<FS>技师：" + "\\r\\n"
			for _, technician := range spaOrder.TechnicianList {
				content = content +
					"技师姓名：" + technician.TechnicianDetail.Name + "\\r\\n" +
					"技师手机：" + technician.TechnicianDetail.PhoneArea + technician.TechnicianDetail.Phone
			}
			content = content + "</FS>\\r\\n"
		}
		content = content + "\\r\\n" + "\\r\\n"

		// 开始打印
		// 新建一个配置实例
		conf := openApi.NewConfig(printer.ClientId, printer.ClientSecret)

		// 获取 token 并设置
		oauth := openApi.NewAuthClient(conf)
		tokenData := oauth.GetAccessToken()
		conf.SetToken(tokenData)

		// 新建一个 API 实例
		client := openApi.NewClient(conf)

		// 添加一个打印机。未绑定打印机，需先调用此方法
		//_, err = client.SetPrinter.AddPrinter(printer.MachineCode, printer.MachineKey, printer.PrinterName)

		// 调用服务 API
		_, _ = client.PrintService.TextPrint(printer.MachineCode, content, spaOrder.OrderSn, 0)
	}

	return
}

// PrinterFoodOrder 打印餐厅订单
func (s *sBasicsPrinter) PrinterFoodOrder(ctx context.Context, in *input_basics.PrinterCarOrderInp) (err error) {

	// 获取打印配置
	var PrinterConfig *model.PrinterSettingConfig
	if PrinterConfig, err = service.BasicsConfig().GetFoodPrinterSettingConfig(ctx); err != nil {
		return
	}

	// 判断是否开启打印功能
	if PrinterConfig.IsOpen == 2 {
		err = gerror.New("未开启打印功能，请稍后重试！")
		return
	}

	if g.IsEmpty(PrinterConfig.PrinterIds) {
		err = gerror.New("未配置打印机，请稍后重试！")
		return
	}

	// 获取打印机信息，默认一号打印机 todo
	var printerArr []*entity.SysPrinter
	if err = dao.SysPrinter.Ctx(ctx).
		WhereIn(dao.SysPrinter.Columns().Id, strings.Split(PrinterConfig.PrinterIds, ",")).
		WithAll().
		Scan(&printerArr); err != nil {
		err = gerror.Wrap(err, "获取打印机信息失败，请稍后重试！")
		return
	}

	// 获取订单信息
	var foodOrder *input_food.FoodOrderViewModel
	if !g.IsEmpty(in.OrderId) {
		if err = dao.FoodOrder.Ctx(ctx).WherePri(in.OrderId).WithAll().Hook(hook.PmsFindLanguageValueHook).Scan(&foodOrder); err != nil {
			err = gerror.Wrap(err, "获取订单信息失败，请稍后重试！")
			return
		}
	} else {
		if err = dao.FoodOrder.Ctx(ctx).Where(dao.FoodOrder.Columns().OrderSn, in.OrderSn).WithAll().Hook(hook.PmsFindLanguageValueHook).Scan(&foodOrder); err != nil {
			err = gerror.Wrap(err, "获取订单信息失败，请稍后重试！")
			return
		}
	}

	// 打印内容
	var orderType = "餐厅"

	// 循环打印机, 判断打印机状态，状态为1时打印
	for _, printer := range printerArr {
		if printer.Status != 1 {
			continue
		}

		var content = ""
		content = content +
			"<MN>" + gvar.New(printer.PrintTimes).String() + "</MN>" +
			"<FS><center>" + orderType + "</center></FS>" + "\\r\\n" +
			//"<FH>" +
			"订单编号：" + foodOrder.OrderSn + "\\r\\n" +
			"订单金额：" + gvar.New(foodOrder.OrderAmount).String() + "JPY\\r\\n" +
			"支付时间：" + gvar.New(foodOrder.PayTime).String() + "\\r\\n" +
			"\\r" +
			"餐厅：" + foodOrder.RestaurantDetail.Name + "\\r\\n" +
			"套餐：" + foodOrder.GoodsDetail.GoodsName + "\\r\\n" +
			"\\r\\n" +
			"预订人信息：\\r\\n" +
			"预订人：" + foodOrder.BookingName + "\\r\\n" +
			"电话：" + foodOrder.PhoneArea + foodOrder.BookingMobile + "\\r\\n" +
			"人数：" + gvar.New(foodOrder.BookingCount).String() + "\\r\\n" +
			"\\r\\n" +
			"备注：" + foodOrder.MemberMessage + "\\r\\n" +
			//"</FH>" +
			"\\r\\n" + "\\r\\n"

		// 开始打印
		// 新建一个配置实例
		conf := openApi.NewConfig(printer.ClientId, printer.ClientSecret)

		// 获取 token 并设置
		oauth := openApi.NewAuthClient(conf)
		tokenData := oauth.GetAccessToken()
		conf.SetToken(tokenData)

		// 新建一个 API 实例
		client := openApi.NewClient(conf)

		// 添加一个打印机。未绑定打印机，需先调用此方法
		//_, _ = client.SetPrinter.AddPrinter(printer.MachineCode, printer.MachineKey, printer.PrinterName)

		// 调用服务 API
		_, _ = client.PrintService.TextPrint(printer.MachineCode, content, foodOrder.OrderSn, 0)
	}

	return
}
